﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "StarrySkyAttributeSet.generated.h"

//创建属性访问器宏
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

//用于声明具有返回值的委托，允许委托函数执行后返回特定类型的值，该委托可以返回 FGameplayAttribute 类型的值
//这样的委托通常用于需要动态获取属性信息的场景
//DECLARE_DELEGATE_RetVal(FGameplayAttribute,FAttributeSignature)

/** 存储游戏效果信息的结构体 */
USTRUCT(BlueprintType)
struct FEffectsProperties
{
	GENERATED_BODY()

	FEffectsProperties() {}
	
	FGameplayEffectContextHandle EffectContextHandle;

	UPROPERTY()
	UAbilitySystemComponent* SourceASC=nullptr;

	UPROPERTY()
	AActor* SourceAvatarActor=nullptr;

	UPROPERTY()
	AController* SourceController=nullptr;

	UPROPERTY()
	ACharacter* SourceCharacter=nullptr;

	UPROPERTY()
	UAbilitySystemComponent* TargetASC=nullptr;

	UPROPERTY()
	AActor* TargetAvatarActor=nullptr;

	UPROPERTY()
	AController* TargetController=nullptr;

	UPROPERTY()
	ACharacter* TargetCharacter=nullptr;
};

//这里创建一个函数模板
//TBaseStaticDelegateInstance是返回T类型的函数指针的类型，FDefaultDelegateUserPolicy是默认的委托用户策略
template<class T>
using TStaticFuncPtr = typename TBaseStaticDelegateInstance<T,FDefaultDelegateUserPolicy>::FFuncPtr;
/**
 * 
 */
UCLASS()
class STARRYSKY_API UStarrySkyAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
public:
	UStarrySkyAttributeSet();
	//重写复制函数
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	//通常是指在某个属性（attribute）发生变化之前所触发的一个事件或回调，可以做一些处理，比如限制最大值等
	virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
	//属性值改变时调用
	virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;

	//保存游戏标签和动态获取属性值委托的映射关系
	//TMap<FGameplayTag,FAttributeSignature> TagsToAttributeSets;
	//map对应关联的函数指针
	//TStaticFuncPtr<FGameplayAttribute()>是一个返回FGameplayAttribute的函数指针
	TMap<FGameplayTag,TStaticFuncPtr<FGameplayAttribute()>> TagsToAttributeSets;
	/**
    * 主要属性，根据游戏类型不同，如果rpg的力量，智力等
    */

	//力量
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Strength,Category="Primary Attributes")
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Strength);
	//智力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Intelligence,Category="Primary Attributes")
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Intelligence);
	//韧性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Resilience,Category="Primary Attributes")
	FGameplayAttributeData Resilience;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Resilience);
	//活力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Vigor,Category="Primary Attributes")
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Vigor);

	/**
	 * 次要属性，依赖于别的属性变化子属性，比如力量，智力派生的属性
	 */

	/* 通过强壮属性影响的次要属性 */
	//护甲
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Armor,Category="Secondary Attributes")
	FGameplayAttributeData Armor;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Armor);

	//穿甲
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_ArmorPenetration,Category="Secondary Attributes")
	FGameplayAttributeData ArmorPenetration;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,ArmorPenetration);

	//格挡率 通过护甲派生的属性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_BlockChance,Category="Secondary Attributes")
	FGameplayAttributeData BlockChance;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,BlockChance);

	//暴击率 通过穿甲派生的属性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_CriticalHitChance,Category="Secondary Attributes")
	FGameplayAttributeData CriticalHitChance;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,CriticalHitChance);

	//暴击伤害 通过穿甲派生的属性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_CriticalHitDamage,Category="Secondary Attributes")
	FGameplayAttributeData CriticalHitDamage;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,CriticalHitDamage);

	//暴击抵抗 通过护甲派生的属性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_CriticalHitResistance,Category="Secondary Attributes")
	FGameplayAttributeData CriticalHitResistance;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,CriticalHitResistance);
	
	/**
	 *根据活力派生出的次要属性
	 */
	//生命恢复速度
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_HealthRegeneration,Category="Secondary Attributes")
	FGameplayAttributeData HealthRegeneration;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,HealthRegeneration);

	//最大生命 由活力派生
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxHealth,Category="Secondary Attributes")
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,MaxHealth);
	
	/**
	 *根据智力派生出的次要属性
	 */
	//法力恢复速度
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_ManaRegeneration,Category="Secondary Attributes")
	FGameplayAttributeData ManaRegeneration;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,ManaRegeneration);

	//最大法力 由智力派生
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxMana,Category="Secondary Attributes")
	FGameplayAttributeData MaxMana;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,MaxMana);
	/**
	* 重要的属性 
	*/
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Health,Category="vital Attributes")
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Health);
	
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Mana,Category="vital Attributes")
	FGameplayAttributeData Mana;
	ATTRIBUTE_ACCESSORS(UStarrySkyAttributeSet,Mana);

	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldHealth) const;
	UFUNCTION()
	void OnRep_Mana(const FGameplayAttributeData& OldMana) const;
	UFUNCTION()
	void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const;
	UFUNCTION()
	void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const;
	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldHealthRegeneration) const;
	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldManaRegeneration) const;
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;
	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const;
	UFUNCTION()
	void OnRep_Resilience(const FGameplayAttributeData& OldResilience) const;
	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldVigor) const;

	//次要属性的回调函数
	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldArmor) const;
	UFUNCTION()
	void OnRep_ArmorPenetration(const FGameplayAttributeData& OldArmorPenetration) const;
	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldBlockChance) const;
	UFUNCTION()
	void OnRep_CriticalHitChance(const FGameplayAttributeData& OldCriticalHitChance) const;
	UFUNCTION()
	void OnRep_CriticalHitDamage(const FGameplayAttributeData& OldCriticalHitDamage) const;
	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldCriticalHitResistance) const;

private:
	//设置游戏效果属性
	void SetEffectProperties(const FGameplayEffectModCallbackData& Data,FEffectsProperties& Properties) const;	
};
